home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / boot / netBoot.new / dev / st.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-19  |  10.8 KB  |  524 lines

  1.  
  2. /*
  3.  * @(#)st.c 1.1 86/09/27 Copyright (c) 1985 by Sun Microsystems, Inc.
  4.  */
  5.  
  6. #include "../dev/saio.h"
  7. #include "../h/param.h"
  8. #include "../h/buf.h"
  9. #include "../dev/dklabel.h"
  10. #include "../dev/dkio.h"
  11. #include "../dev/screg.h"
  12. #include "../dev/sireg.h"
  13. #include "../dev/scsi.h"
  14. #include "../dev/streg.h"
  15. #include "../h/idprom.h"
  16.  
  17. /*
  18.  * Driver for Sysgen SC4000 and EMULEX MT-02 SCSI tape controllers.
  19.  * Supports qic11 format only.
  20.  */
  21. extern int scdoit();
  22. #ifdef SUN3
  23. extern int sidoit();
  24. #endif
  25.  
  26. #define min(a,b)    ((a)<(b)? (a): (b))
  27.  
  28. #define NSD 1
  29. unsigned long staddrs[NSD] = { 0x0, };
  30.  
  31. extern int xxprobe(), ttboot();
  32. int stopen(), stclose(), ststrategy();
  33.  
  34.  
  35. struct stparam {
  36.     int        st_target;
  37.     int        st_unit;
  38.     int        st_eof;
  39.     int        st_lastcmd;
  40.     int        st_ctype;
  41. #ifdef SUN3
  42.     int        st_ha_type;
  43. #endif
  44.     struct         saioreq subsip[1];    /* sip for host adapter */
  45. };
  46.  
  47. /*
  48.  * DMA-able buffers
  49.  */
  50. #ifdef SUN2
  51. /* virtual addresses are precious on Sun-2 */
  52. #define    MAXSTBSIZE    (20*1024)    
  53. #endif
  54. #ifdef SUN3
  55. #define    MAXSTBSIZE    (127*512)    
  56. #endif
  57. struct stdma {
  58.     char    sbuffer[SENSE_LENGTH];
  59.     char    databuffer[MAXSTBSIZE];
  60. };
  61.  
  62. #define STSBUF        (((struct stdma *)sip->si_dmaaddr)->sbuffer)
  63. #define STBUF        (((struct stdma *)sip->si_dmaaddr)->databuffer)
  64.  
  65. #define ISAEMULEX(stp)    (stp->st_ctype == ST_TYPE_EMULEX ? 1 : 0)
  66.  
  67. /*
  68.  * What resources we need to run
  69.  */
  70. struct devinfo stinfo = {
  71.     0,                /* No device to map in */
  72.     sizeof (struct stdma),
  73.     sizeof (struct stparam),
  74.     NSD,                /* Dummy devices */
  75.     staddrs,            /* Dummy devices */
  76.     MAP_MAINMEM,
  77.     MAXSTBSIZE,            /* transfer size */
  78. };
  79.  
  80. struct boottab stdriver = {
  81.     "st",    xxprobe, ttboot,
  82.     stopen, stclose, ststrategy,
  83.     "st: SCSI tape", &stinfo
  84. };
  85.  
  86. #define    TAPE_TARGET        4    /* default SCSI target # for tape */
  87.  
  88. #define SENSELOC    4    /* sysgen returns sense at this offset */
  89.  
  90. #define    ROUNDUP(x)    ((x + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1))
  91.  
  92. #ifdef SUN3
  93. /*
  94.  * Determine type of host adaptor interface, si or sc.
  95.  * Returns 1 if si host adaptor and 0 if sc host adaptor.
  96.  */
  97. st_probe(sip)
  98.     struct saioreq *sip;
  99. {
  100.     if (siprobe(sip)) {
  101.         return (1);
  102.     } else {
  103.         return (0);
  104.     }
  105. }
  106. #endif
  107.  
  108. /*
  109.  * Open the SCSI Tape controller
  110.  */
  111. int
  112. stopen(sip)
  113.     register struct saioreq *sip;
  114. {
  115.     register struct stparam *stp;
  116.     register int r;
  117.     register int skip;
  118.     register int i;
  119.     struct scsi_cdb cdb;
  120.     struct scsi_scb scb;
  121.  
  122.     stp = (struct stparam *) sip->si_devdata;
  123.     bzero( (char *)stp, (sizeof (struct stparam)));
  124.  
  125.     *stp->subsip = *sip;    /* initialize subsip */
  126.  
  127. #ifdef SUN3
  128.     {
  129.         extern struct boottab scdriver;
  130.         extern struct boottab sidriver;
  131.  
  132.         /* FIXME, find out which scsi interface to use */
  133.         if (st_probe(sip)) {
  134.             stp->st_ha_type = 1;
  135.  
  136.             /* FIXME, must vector thru table */
  137.             stp->subsip->si_boottab = &sidriver;
  138.         } else {
  139.             stp->st_ha_type = 0;
  140.  
  141.             /* FIXME, must vector thru table */
  142.             stp->subsip->si_boottab = &scdriver;
  143.         }
  144.     }
  145. #endif
  146. #ifdef SUN2
  147.     {
  148.         extern struct boottab scdriver;
  149.  
  150.         stp->subsip->si_boottab = &scdriver;    
  151.     }
  152. #endif
  153.  
  154.     stp->subsip->si_unit = sip->si_unit >> 3;       /* Target number */
  155.     if (stp->subsip->si_unit == 0) {
  156.         stp->subsip->si_unit = TAPE_TARGET;
  157.     }
  158.  
  159.     r = devopen(stp->subsip);
  160.     if (r < 0) return r;
  161.  
  162.     /* Logical unit number */
  163.     stp->st_unit = sip->si_unit & 0x07;
  164.  
  165.     /*
  166.      * Must wait for tape controller to become ready.
  167.      * This takes about 10 seconds for the Emulex.
  168.      */
  169. #ifndef M25
  170.     DELAY(10000000);
  171. #endif
  172.     /*
  173.      * Test for the controller being ready. First test will fail if
  174.      * the SCSI bus is permanently busy or if a previous op was 
  175.      * interrupted in mid-transfer. Second one should work.
  176.      */
  177. #ifdef M25
  178.     do {
  179.         bzero((char *) &cdb, sizeof cdb);
  180.         cdb.cmd = SC_TEST_UNIT_READY;
  181.         cdb.count = 0;
  182.         stp->subsip->si_cc = 0;
  183.         stp->subsip->si_ma = 0;
  184.         r = sidoit(&cdb, &scb, stp->subsip);
  185.         DELAY(10000);
  186.     } while (scb.busy);
  187. #else M25
  188.     for (i = 0; i < 2; i++) {
  189.         bzero((char *) &cdb, sizeof cdb);
  190.         cdb.cmd = SC_TEST_UNIT_READY;
  191.         cdb.count = 0;
  192.         stp->subsip->si_cc = 0;
  193.         stp->subsip->si_ma = 0;
  194. #ifdef SUN3
  195.         if (stp->st_ha_type)
  196.             r = sidoit(&cdb, &scb, stp->subsip);
  197.         else
  198. #endif
  199.             r = scdoit(&cdb, &scb, stp->subsip);
  200.     }
  201. #endif M25                                
  202.  
  203.     /* 
  204.      * To figure out what type of tape controller is out there we send 
  205.      * a REQUEST_SENSE command and see how much sense data comes back.  
  206.      */
  207.     stp->st_ctype = ST_TYPE_EMULEX;
  208.     cdb.cmd = SC_REQUEST_SENSE;
  209.     stp->subsip->si_cc = cdb.count = ST_EMULEX_SENSE_LEN;
  210.     stp->subsip->si_ma = STSBUF;
  211. #ifdef SUN3
  212.     if (stp->st_ha_type)
  213.         r = sidoit(&cdb, &scb, stp->subsip);
  214.     else
  215. #endif
  216.         r = scdoit(&cdb, &scb, stp->subsip);
  217.     if (r != ST_EMULEX_SENSE_LEN) {
  218.             stp->st_ctype = ST_TYPE_SYSGEN;
  219.         cdb.cmd = SC_REQUEST_SENSE;
  220.         stp->subsip->si_cc = cdb.count = ST_SYSGEN_SENSE_LEN;
  221.         stp->subsip->si_ma = STSBUF;
  222. #ifdef SUN3
  223.         if (stp->st_ha_type)
  224.             r = sidoit(&cdb, &scb, stp->subsip);
  225.         else
  226. #endif
  227.             r = scdoit(&cdb, &scb, stp->subsip);
  228.         if (r == -1) {
  229.             printf("stopen: cannot get sense, %d\n", r);
  230.             return (-1);
  231.         }
  232.     } 
  233.  
  234.     /* 
  235.      * Default format mode for emulex is qic24.
  236.      * Needs to be qic11.
  237.      */
  238.     if (ISAEMULEX(stp)) {
  239.         sip->si_cc = EM_MS_PL_LEN;
  240.         if (stcmd(SC_QIC11, sip, 1) == 0) {
  241.             printf("stopen: mode select command fail");
  242.             return (-1);
  243.         }
  244.     }
  245.  
  246.     /*
  247.      * Rewind a few times until it works.  First one will fail if
  248.      * the SCSI bus is permanently busy if a previous op was interrupted
  249.      * in mid-transfer.  Second one will fail with POR status, after
  250.      * the scsi bus is reset from the busy.  Third one should work.  
  251.      */
  252.     sip->si_cc = 0;
  253.     if (stcmd(SC_REWIND, sip, 0) == 0 &&
  254.         stcmd(SC_REWIND, sip, 0) == 0 &&
  255.         stcmd(SC_REWIND, sip, 1) == 0) {
  256.         return (-1);
  257.     }
  258.     sip->si_cc = 512;
  259.     sip->si_ma = STSBUF;
  260.     if (stcmd(SC_READ, sip, 0) == -2) {
  261.         sip->si_cc = 0;
  262.         stcmd(SC_QIC24, sip, 1);
  263.     }
  264.     sip->si_cc = 0;
  265.     stcmd(SC_REWIND, sip, 1); /* rewind again to be safe */
  266.     skip = sip->si_boff;
  267.     while (skip--) {
  268.         sip->si_cc = 0;
  269.         if (stcmd(SC_SPACE_FILE, sip, 1) == 0) {
  270.             return (-1);
  271.         }
  272.     }
  273.     stp->st_eof = 0;
  274.     stp->st_lastcmd = 0;
  275.     return (0);
  276. }
  277.  
  278. /*
  279.  * Close the tape drive.
  280.  */
  281. stclose(sip)
  282.     register struct saioreq *sip;
  283. {
  284.     register struct stparam *stp;
  285.  
  286.     stp = (struct stparam *) sip->si_devdata;
  287.     if (stp->st_lastcmd == SC_WRITE) {
  288.         (void) stcmd(SC_WRITE_FILE_MARK, sip, 0);
  289.     }
  290.     (void) stcmd(SC_REWIND, sip, 0);
  291.     if (ISAEMULEX(stp)) {
  292.         sip->si_cc = EM_MS_PL_LEN;
  293.         if (stcmd(SC_QIC11, sip, 1) == 0) {
  294.             printf("stclose: mode select command fail");
  295.             return (-1);
  296.         }
  297.     } else {
  298.         sip->si_cc = 0;
  299.         if (stcmd(SC_QIC11, sip, 1) == 0) {
  300.             printf("stclose: mode select command fail");
  301.             return (-1);
  302.         }
  303.     }
  304. }
  305.  
  306.  
  307. /*
  308.  * Perform a read or write of the SCSI tape.
  309.  */
  310. int
  311. ststrategy(sip, rw)
  312.     register struct saioreq *sip;
  313.     int rw;
  314. {
  315.     register struct stparam *stp;
  316.  
  317.     stp = (struct stparam *) sip->si_devdata;
  318.     if (stp->st_eof) {
  319.         stp->st_eof = 0;
  320.         return (0);
  321.     }
  322.     return (stcmd(rw == WRITE ? SC_WRITE : SC_READ, sip, 1));
  323. }
  324.  
  325. /*
  326.  * Execute a scsi tape command
  327.  */
  328. int
  329. stcmd(cmd, sip, errprint)
  330.     int cmd;
  331.     register struct saioreq *sip;
  332.     int errprint;
  333. {
  334.     register struct st_emulex_mspl *mode;
  335.     register int r, i, c;
  336.     register char *buf;
  337.     register struct stparam *stp;
  338.     struct scsi_cdb cdb, scdb;
  339.     struct scsi_scb scb, sscb;
  340.     int count;
  341.     int qic;
  342.     int sense_length;
  343.     char *cp;
  344.     struct st_emulex_sense *ems;
  345.     struct st_sysgen_sense *scs;
  346.  
  347.     count = sip->si_cc;
  348.     stp = (struct stparam *)sip->si_devdata;
  349.     buf =  sip->si_ma;
  350.  
  351.     if (cmd == SC_WRITE && buf != STBUF) {
  352.         bcopy(buf, STBUF, (unsigned)count);
  353.     }
  354.  
  355.     /* set up cdb */
  356.     bzero((char *) &cdb, sizeof cdb);
  357.     cdb.cmd = cmd;
  358.     cdb.lun = stp->st_unit;
  359.     c = ROUNDUP(count) / DEV_BSIZE;
  360.     cdb.high_count = c >> 16;
  361.     cdb.mid_count = (c >> 8) & 0xFF;
  362.     cdb.low_count = c & 0xFF;
  363.     stp->subsip->si_ma = STBUF;
  364.     stp->subsip->si_cc = ROUNDUP(count);
  365.  
  366.     /* some fields in the cdb are command specific */
  367.     switch (cmd) {
  368.  
  369.     case SC_QIC11:
  370.             stp->subsip->si_ma = 0;
  371.             stp->subsip->si_cc = 0; 
  372.         if (ISAEMULEX(stp)) {
  373.             qic = ST_EMULEX_QIC11;
  374.             cdb.cmd = SC_MODE_SELECT;
  375.             goto MODE;
  376.         } else {
  377.             cdb.cmd = SC_QIC02;
  378.             cdb.high_count = ST_SYSGEN_QIC11;
  379.             break;
  380.         }
  381.         /* NOTREACHED */
  382.  
  383.     case SC_QIC24:
  384.             stp->subsip->si_ma = 0;
  385.             stp->subsip->si_cc = 0; 
  386.         if (ISAEMULEX(stp)) {
  387.             qic = ST_EMULEX_QIC24;
  388.             cdb.cmd = SC_MODE_SELECT;
  389.             goto MODE;
  390.         } else {
  391.             cdb.cmd = SC_QIC02;
  392.             cdb.high_count = ST_SYSGEN_QIC24;
  393.             break;
  394.         }
  395.         /* NOTREACHED */
  396. MODE:
  397.     case SC_MODE_SELECT:
  398.          mode = (struct st_emulex_mspl *)STSBUF;
  399.         bzero(mode, sizeof(*mode));
  400.         mode->hdr.bufm = 1;
  401.         mode->bd.density = qic;
  402.         mode->hdr.bd_len = EM_MS_BD_LEN;
  403.         stp->subsip->si_ma = (char *)mode;
  404.         stp->subsip->si_cc = cdb.count = EM_MS_PL_LEN;
  405.         break;
  406.  
  407.     case SC_SPACE_FILE:
  408.         cdb.cmd = SC_SPACE;    /* the real SCSI cmd */
  409.         cdb.t_code = 1;        /* space file, not rec */
  410.         cdb.low_count = 1;    /* space 1 file, not 0 */
  411.         stp->subsip->si_ma = 0;
  412.         stp->subsip->si_cc = 0;
  413.         break;
  414.  
  415.     case SC_WRITE_FILE_MARK:
  416.         cdb.count = 1;    
  417.         /* fall through... */
  418.  
  419.     case SC_TEST_UNIT_READY:
  420.     case SC_REWIND:
  421.     case SC_LOAD:
  422.         stp->subsip->si_ma = 0;
  423.         stp->subsip->si_cc = 0;
  424.         break;
  425.  
  426.     case SC_READ:
  427.     case SC_WRITE:
  428.          if (ISAEMULEX(stp)) {
  429.                 cdb.t_code = 1;
  430.         }
  431.         break;
  432.  
  433.     default:
  434.         if (errprint)
  435.             printf("st: unknown command\n");
  436.         return (0);
  437.     }
  438.  
  439.     /* execute the command */
  440. #ifdef SUN3
  441.     if (stp->st_ha_type)
  442.         r = sidoit(&cdb, &scb, stp->subsip);
  443.     else
  444. #endif
  445.         r = scdoit(&cdb, &scb, stp->subsip);
  446.  
  447.     /* allow for tape blocking */
  448.     if (r > count)
  449.         r = count;
  450.     /* error */
  451.     if (r == -1) 
  452.         return (0);
  453.  
  454.     if (cmd == SC_READ) {
  455.         if (min(count, r))
  456.             bcopy(STBUF, buf, (unsigned)(min(count, r)));
  457.     }
  458.  
  459.     /* we may need to get sense data */
  460.     if (scb.chk) {
  461.         bzero((char *) &scdb, sizeof scdb);
  462.         scdb.cmd = SC_REQUEST_SENSE;
  463.         scdb.lun = stp->st_unit;
  464.         if (ISAEMULEX(stp)) {
  465.             sense_length = stp->subsip->si_cc =
  466.                 scdb.count = ST_EMULEX_SENSE_LEN;
  467.         } else {
  468.             sense_length = stp->subsip->si_cc = 
  469.                 scdb.count = ST_SYSGEN_SENSE_LEN;
  470.         }
  471.         stp->subsip->si_ma = STSBUF;
  472. #ifdef SUN3
  473.         if (stp->st_ha_type)
  474.             i = sidoit(&scdb, &sscb, stp->subsip );
  475.         else
  476. #endif
  477.             i = scdoit(&scdb, &sscb, stp->subsip );
  478.         if (i != sense_length) {
  479.             if (errprint) {
  480.                 printf("st: sense error\n");
  481.             }
  482.             stp->st_eof = 1;
  483.             return (0);
  484.         } 
  485.         if (ISAEMULEX(stp)) {
  486.             ems = (struct st_emulex_sense *)STSBUF;
  487.             stp->st_eof = 1;
  488.             if ((ems->ext_sense.key == 0x8) &&
  489.                    (ems->error == 0x34))
  490.                 return(-2);
  491.             if ((ems->ext_sense.fil_mk == 0) && errprint) {
  492.                 printf("st: error:\n");
  493.                 printf("\tsense key is %x", 
  494.                     ems->ext_sense.key);
  495.                 printf("\terror is %x\n",
  496.                     ems->error);
  497.             }
  498.             return (r);
  499.         } else  {
  500.             scs = (struct st_sysgen_sense *)STSBUF;
  501.             stp->st_eof = 1;
  502.             if (*(unsigned short *)&STSBUF[SENSELOC] == 0x86a8)
  503.                 return(-2);
  504.             if ((scs->qic_sense.file_mark == 0) && errprint) {
  505.                 printf("st: error %x\n", 
  506.                     *(unsigned short *)&STSBUF[SENSELOC]);
  507.             }
  508.             return (r);
  509.         }
  510.     }
  511.     if (r >= count) {
  512.         return (count ? count : 1);
  513.     } else {
  514.         if (errprint) {
  515.             printf("st: short transfer\n");
  516.         }
  517.         return (r);
  518.     }
  519. }
  520.  
  521.  
  522.  
  523.  
  524.